package cn.virens.common.boot.rabbit;

import cn.virens.common.boot.rabbit.autoconfig.RabbitManageProperties;
import cn.virens.common.util.exception.APIException;
import com.alibaba.fastjson2.JSON;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.reflect.ClassUtil;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;

import static java.nio.charset.StandardCharsets.UTF_8;

public class RabbitManagerSimple implements RabbitManager {
    protected final RabbitManageProperties properties;
    protected final RabbitTemplate mRabbitTemplate;

    public RabbitManagerSimple(RabbitManageProperties properties, RabbitTemplate mRabbitTemplate) {
        this.mRabbitTemplate = mRabbitTemplate;
        this.properties = properties;
    }

    @Override
    public <T> Object sendSync(T data) throws APIException {
        Message message = formatMessageAndProperties(data);
        String routingKey = formatMessageRoutingKey(data);
        String exchange = formatMessageExchange(data);

        // 发送消息，并等待应答-----------------------------------------
        Message receive = sendSync(exchange, routingKey, message);
        if (receive == null || receive.getBody() == null) {//
            throw new APIException("REPLY_ERR", "发送失败");
        }

        // 获取应答消息数据---------------------------------------------
        var prop = receive.getMessageProperties();
        var resultBody = receive.getBody();

        return deserialize(resultBody, prop);
    }

    @Override
    public <T> T sendAsyn(T data) throws APIException {
        Message message = formatMessageAndProperties(data);
        String routingKey = formatMessageRoutingKey(data);
        String exchange = formatMessageExchange(data);

        sendAsyn(exchange, routingKey, message);

        return data;
    }

    /**
     * 构建消息包
     */
    protected <T> Message formatMessageAndProperties(T data) throws APIException {
        MessageProperties properties = new MessageProperties();
        properties.setHeader("data-class", ClassUtil.getClassName(data, true));
        properties.setContentType(MessageProperties.CONTENT_TYPE_JSON);

        // 完成来源数据转码到byte数组-------------------------------
        byte[] bodyByte = serialize(data, properties);

        // 根据byte数组填充当前消息的信息----------------------------
        properties.setContentLength(bodyByte.length);
        properties.setContentEncoding(UTF_8.name());
        properties.setTimestamp(DateUtil.now());

        // 构建Rabbit数据包--------------------------------------
        return new Message(bodyByte, properties);
    }

    /**
     * 获取队列路由键
     */
    protected <T> String formatMessageRoutingKey(T data) throws APIException {
        return RabbitManagerUtil.routingKey(data);
    }

    /**
     * 获取队列路由
     */
    protected <T> String formatMessageExchange(T data) throws APIException {
        return properties.getExchangeDefault();
    }

    /**
     * 序列化消息应答
     */
    protected Object deserialize(byte[] data, MessageProperties properties) {
        return null;
    }

    /**
     * 消息序列化
     */
    protected <T> byte[] serialize(T data, MessageProperties properties) {
        return JSON.toJSONBytes(data);
    }

    /**
     * 执行异步发送操作
     */
    protected void sendAsyn(String exchange, String routingKey, Message message) {
        mRabbitTemplate.send(exchange, routingKey, message);
    }

    /**
     * 执行同步发送操作
     */
    protected Message sendSync(String exchange, String routingKey, Message message) {
        return mRabbitTemplate.sendAndReceive(exchange, routingKey, message);
    }

}
